package com.frontyard.chatty.connection.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayDeque;
import java.util.Deque;

import com.frontyard.chatty.connection.ChattyMessage;
import com.frontyard.chatty.connection.ClientConnection;
import com.frontyard.chatty.connection.listener.ChattyClientListener;
import com.frontyard.chatty.util.SocketUtil;

public class ClientConnectionImpl implements ClientConnection {

    private ChattyClientListener listener;

    private Deque<String> messages = new ArrayDeque<String>();

    private Socket socket;

    private PrintWriter out;
    private BufferedReader in;

    public boolean open(String host) {
        try {
            socket = SocketUtil.createAndConnect(host, CHATTY_PORT);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            listen();
        } catch (IOException e) {
            socket = null;
            out = null;
            in = null;
            return false;
        }
        return true;
    }

    public void close() {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendPublicMessage(String payload) {
        if (out != null) {
            messages.add(payload);
        }
    }

    public void setClientListener(ChattyClientListener listener) {
        this.listener = listener;
    }

    public void listen() {

        Thread connectionListener = new Thread() {

            public void run() {
                try {
                    String input;
                    while ((input = in.readLine()) != null) {
                        processMessage(input);
                        // send anything that needs to be sent
                        if (messages.isEmpty()) {
                            out.println(ChattyMessage.PUBL.name() + messages.poll());
                        }
                    }
                } catch (IOException e) {
                    listener.onError(e.getMessage());
                    e.printStackTrace();
                }
            }
        };

        connectionListener.start();
    }

    public void processMessage(String message) {
        if (message.length() > 0) {
            String type = message.substring(0, 4);
            String data = message.substring(4);
            switch (ChattyMessage.valueOf(type)) {
            case PUBL:
                listener.onPublicMessage(data);
            case JOIN:
                listener.onJoin(data);
            case LEFT:
                listener.onLeft(data);
                break;
            case ACKN:
                // ignored by default
                break;

            default:
                break;
            }
        }
    }
}
